/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package BO;

import UI.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Persistence;

/**
 *
 * @author Wase
 */
public class Controller {

    private EntityManager em = Persistence.createEntityManagerFactory("ToWaCommunityPU").createEntityManager();
    //private static User ussur;

    public Controller() {
        //ussur = (User) em.createNamedQuery("User.findById").setParameter("id", 7).getSingleResult();
    }

    public UserView validate(String username, String password) {
        User u = null;
        try {
            u = (User) em.createQuery("SELECT u FROM User u WHERE u.username='" + username
                    + "' AND u.password='" + password + "'").getSingleResult();
        } catch (IllegalStateException ise) {
        } catch (IllegalArgumentException iae) {
        }
        UserView uw = new UserView(u.getId(), u.getUsername(), u.getFirstName(), u.getSurName(), u.getAddress(), u.getZipcode(), u.getCity(), u.getCountry(), u.getEmail());
        return uw;
    }

    public String register(String username, String password,
            String firstName, String surName, String address,
            String zipcode, String city, String country, String email) {
        User u = new User();
        u.setUsername(username);
        u.setPassword(password);
        u.setFirstName(firstName);
        u.setSurName(surName);
        u.setAddress(address);
        u.setZipcode(zipcode);
        u.setCity(city);
        u.setCountry(country);
        u.setEmail(email);
        try {
            em.getTransaction().begin();
            em.persist(u);
            em.flush();
            em.getTransaction().commit();
            return "registered";
        } catch (javax.persistence.EntityExistsException e) {
            em.getTransaction().rollback();
            return "notRegistered";
        }
    }

    public String removeFriend(Integer userId, Integer friendId) {
        Friends fri = null;
        try {
            fri = (Friends) em.createQuery("SELECT f FROM Friends f WHERE (f.userId=" + userId + " AND f.friendId=" + friendId + ") OR ("
                    + "f.friendId=" + userId + " AND f.userId=" + friendId + ")").getSingleResult();
        } catch (NoResultException e) {
        }
        if (fri != null) {
            try {
                em.getTransaction().begin();
                em.remove(fri);
                em.flush();
                em.getTransaction().commit();
                return "unfriended";
            } catch (javax.persistence.EntityExistsException e) {
                em.getTransaction().rollback();
            }
        }
        return "notUnfriended";
    }

    public String stalkable(Integer userId, Integer friendId) {
        if (userId != friendId) {
            Friends fri = null;
            try {
                fri = (Friends) em.createQuery("SELECT f FROM Friends f WHERE (f.userId=" + userId + " AND f.friendId=" + friendId + ") OR ("
                        + "f.friendId=" + userId + " AND f.userId=" + friendId + ")").getSingleResult();
            } catch (NoResultException e) {
            }
            if (fri == null) {
                return "befriendable";
            }
        }
        return "notBefriendable";
    }

    public String makeFriend(Integer userId, Integer friendId) {
        if (userId != friendId) {
            User u = (User) em.createNamedQuery("User.findById").setParameter("id", userId).getSingleResult();
            User f = (User) em.createNamedQuery("User.findById").setParameter("id", friendId).getSingleResult();
            Friends fri = null;
            try {
                fri = (Friends) em.createQuery("SELECT f FROM Friends f WHERE (f.userId=" + userId + " AND f.friendId=" + friendId + ") OR ("
                        + "f.friendId=" + userId + " AND f.userId=" + friendId + ")").getSingleResult();
            } catch (NoResultException e) {
            }
            if (fri == null) {
                try {
                    em.getTransaction().begin();
                    Friends friends = new Friends();
                    friends.setFriendId(f);
                    friends.setUserId(u);
                    em.persist(friends);
                    em.flush();
                    em.getTransaction().commit();
                    return "befriended";
                } catch (javax.persistence.EntityExistsException e) {
                    em.getTransaction().rollback();
                }
            } else if (fri != null) {
                return "alreadyFriended";
            }
        }
        return "notBefriended";
    }

    public String submitPostIt(Integer userId, String content) {
        User u = (User) em.createNamedQuery("User.findById").setParameter("id", userId).getSingleResult();
        List<Postit> postitList = u.getPostitList();
        try {
            em.getTransaction().begin();
            Postit postit = new Postit();
            postit.setContent(content);
            postit.setUserId(u);
            postit.setDatePosted(new Date());
            postitList.add(postit);
            u.setPostitList(postitList);
            em.persist(u);
            em.flush();
            em.getTransaction().commit();
            return "postitAdded";
        } catch (javax.persistence.EntityExistsException e) {
            em.getTransaction().rollback();
        }
        return "postitNotAdded";
    }

    private List<Postit> getPostitsByUserId(Integer userId) {
        List<Postit> postits = em.createQuery("SELECT p from Postit p WHERE p.userId=" + userId.intValue()).getResultList();
        return postits;
    }

    public List<Postit> getLatestPostitsByUserId(Integer userId) {
        ArrayList<Postit> bigList = new ArrayList<Postit>();
        ArrayList<Postit> ownPostits = new ArrayList<Postit>(getPostitsByUserId(userId));
        for (int i = 0; i < ownPostits.size(); i++) {
            bigList.add(ownPostits.get(i));
        }
        List<Friends> friend = em.createQuery("SELECT f FROM Friends f WHERE f.userId=" + userId).getResultList();
        List<Friends> friend2 = em.createQuery("SELECT f FROM Friends f WHERE f.friendId=" + userId).getResultList();
        ArrayList<Postit> friendsPostits;
        for (int i = 0; i < friend.size(); i++) {
            friendsPostits = new ArrayList<Postit>(getPostitsByUserId(friend.get(i).getFriendId().getId()));
            bigList.addAll(friendsPostits);
        }
        for (int i = 0; i < friend2.size(); i++) {
            friendsPostits = new ArrayList<Postit>(getPostitsByUserId(friend2.get(i).getUserId().getId()));
            bigList.addAll(friendsPostits);
        }
        Collections.sort(bigList);
        if (bigList.size() > 5) {
            bigList = new ArrayList<Postit>(bigList.subList(0, 5));
        }
        return bigList;
    }

    public  boolean submitPrivateMessage(Integer userId, String targetName, String title, String content) {
        User u = (User) em.createNamedQuery("User.findById").setParameter("id", userId).getSingleResult();
        User t = (User) em.createNamedQuery("User.findByUsername").setParameter("username", targetName).getSingleResult();
        return submitPrivateMessage(u, t, title, content);
    }

    public  boolean submitPrivateMessage(Integer userId, Integer targetId, String title, String content) {
       User u = (User) em.createNamedQuery("User.findById").setParameter("id", userId).getSingleResult();
       User t = (User) em.createNamedQuery("User.findById").setParameter("id", targetId).getSingleResult();
       return submitPrivateMessage(u, t, title, content);  
    }
    
    private boolean submitPrivateMessage(User from, User to, String title, String content) {
        try {
            em.getTransaction().begin();
            Privatemessage pm = new Privatemessage();
            pm.setUserId(from);
            pm.setTargetId(to.getId());
            pm.setTitle(title);
            pm.setDate(new Date());
            pm.setContent(content);
            from.getPrivatemessageList().add(pm);
            to.getPrivatemessageList().add(pm);
            em.persist(to);
            em.persist(from);
            em.persist(pm);
            em.flush();
            em.getTransaction().commit();
            return true;
        } catch (javax.persistence.EntityExistsException e) {
            em.getTransaction().rollback();
        }
        return false;
    }

    public ArrayList<PrivatemessageView> getPrivateMessagesSentByUserId(Integer userId) {
        List<Privatemessage> privateMessages = em.createQuery("SELECT p FROM Privatemessage p WHERE p.userId=" + userId).getResultList();
        ArrayList<PrivatemessageView> privateList = new ArrayList<PrivatemessageView>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd H:mm:ss");
        for(Privatemessage pm : privateMessages){
            User u = getUserByIdPriv(pm.getTargetId());
            privateList.add(new PrivatemessageView(pm.getId(),pm.getUserId().getUsername(),u.getUsername(),pm.getTitle(),sdf.format(pm.getDate()), pm.getContent()));
        }
        Collections.reverse(privateList);
        return privateList;
    }

    public ArrayList<PrivatemessageView> getPrivateMessagesReceivedByUserId(Integer userId) {
        List<Privatemessage> privateMessages = em.createQuery("SELECT p FROM Privatemessage p WHERE p.targetId=" + userId).getResultList();
        ArrayList<PrivatemessageView> privateList = new ArrayList<PrivatemessageView>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd H:mm:ss");
        for(Privatemessage pm : privateMessages){
            User u = pm.getUserId();
            privateList.add(new PrivatemessageView(pm.getId(), pm.getUserId().getUsername(),u.getUsername(),pm.getTitle(),sdf.format(pm.getDate()), pm.getContent()));
        }
        Collections.reverse(privateList);
        return privateList;
    }
    
    public PrivatemessageView getprivateMessageById(int id){
        Privatemessage pm = (Privatemessage) em.createQuery("SELECT p FROM Privatemessage p WHERE p.id=" + id).getSingleResult();
        User u = getUserByIdPriv(pm.getTargetId());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd H:mm:ss");
        return new PrivatemessageView(pm.getId(),pm.getUserId().getUsername(),u.getUsername(),pm.getTitle(),sdf.format(pm.getDate()), pm.getContent());
    }

    public UserView getUserById(int id) {
        User u = null;
        try {
            u = (User) em.createQuery("SELECT u FROM User u WHERE u.id = " + id).getSingleResult();
        } catch (NoResultException e) {
        }
        UserView uw = new UserView(u.getId(), u.getUsername(), u.getFirstName(), u.getSurName(), u.getAddress(), u.getZipcode(), u.getCity(), u.getCountry(), u.getEmail());
        return uw;
    }

    public List<UserView> findUsers(String username) {
        List<User> list =
                em.createQuery("Select u FROM User u where u.username like '%" + username + "%'").getResultList();
        ArrayList<UserView> viewList = new ArrayList<UserView>();
        for (User u : list) {
            viewList.add(new UserView(u.getId(), u.getUsername(), u.getFirstName(), u.getSurName(), u.getAddress(), u.getZipcode(), u.getCity(), u.getCountry(), u.getEmail()));
        }
        return viewList;
    }

    public ArrayList<ChatView> getMessageAfter(int id, Date start) {
        List<Chat> list;
        SimpleDateFormat sdf;
        if (id > 0) {
            list = em.createQuery("Select c FROM Chat c where c.id > " + id).getResultList();
        } else {
            sdf = new SimpleDateFormat("yyyy-MM-dd H:mm:ss");
            list = em.createQuery("Select c FROM Chat c where c.posted > '" + sdf.format(start) + "'").getResultList();
        }

        ArrayList<ChatView> dcList = new ArrayList<ChatView>();
        sdf = new SimpleDateFormat("[H:mm:ss]");
        for (Chat c : list) {
            ChatView dc = new ChatView();
            dc.setId(c.getId());
            dc.setDate(sdf.format(c.getPosted()));
            dc.setContent(c.getContent());
            dc.setUsername(c.getUserId().getUsername());
            dcList.add(dc);
        }
        return dcList;
    }

    private User getUserByIdPriv(int userId) {
        User u = null;
        try {
            u = (User) em.createQuery("SELECT u FROM User u WHERE u.id = " + userId).getSingleResult();
        } catch (NoResultException e) {
        }
        return u;
    }

    public int addChatMessage(Date time, String message, int userId) {
        User u = getUserByIdPriv(userId);
        Chat c = new Chat();
        c.setPosted(time);
        c.setContent(message);
        c.setUserId(u);
        try {
            em.getTransaction().begin();
            em.persist(c);
            em.flush();
            em.getTransaction().commit();
        } catch (javax.persistence.EntityExistsException e) {
            em.getTransaction().rollback();
        }
        return c.getId();
    }

    public boolean updateProfile(int id, String firstName, String surName, String address, String zipcode, String city, String country) {
        User u = getUserByIdPriv(id);
        if (u == null) {
            return false;
        }
        try {
            em.getTransaction().begin();
            u.setFirstName(firstName);
            u.setSurName(surName);
            u.setAddress(address);
            u.setZipcode(zipcode);
            u.setCity(city);
            u.setCountry(country);
            em.getTransaction().commit();
        } catch (Exception e) {
            em.getTransaction().rollback();
            return false;
        }
        return true;
    }

    public boolean updatePassword(int id, String oldPassword, String password, String confirmPassword) {
        User u = getUserByIdPriv(id);
        if (u == null || !password.equals(confirmPassword)) {
            return false;
        }
        if (!u.getPassword().equals(oldPassword)) {
            return false;
        }
        try {
            em.getTransaction().begin();
            u.setPassword(password);
            em.getTransaction().commit();
        } catch (Exception e) {
            em.getTransaction().rollback();
            return false;
        }
        return true;
    }

    public List<UserView> getFriendsByUserId(Integer id) {
        List<Friends> userIdList = em.createQuery("SELECT f FROM Friends f WHERE f.userId=" + id).getResultList();
        List<Friends> friendIdList = em.createQuery("SELECT f FROM Friends f WHERE f.friendId=" + id).getResultList();
        ArrayList<UserView> friendsList = new ArrayList<UserView>();
        for (Friends friend : userIdList) {
            if (friend.getUserId().getId() == id.intValue()) {
                User friendUser = friend.getFriendId();
                friendsList.add(new UserView(friendUser.getId(), friendUser.getUsername(), friendUser.getFirstName(), friendUser.getSurName(), friendUser.getAddress(), friendUser.getZipcode(), friendUser.getCity(), friendUser.getCountry(), friendUser.getEmail()));
            }
        }
        for (Friends friend : friendIdList) {
            if (friend.getFriendId().getId() == id.intValue()) {
                User friendUser = friend.getUserId();
                friendsList.add(new UserView(friendUser.getId(), friendUser.getUsername(), friendUser.getFirstName(), friendUser.getSurName(), friendUser.getAddress(), friendUser.getZipcode(), friendUser.getCity(), friendUser.getCountry(), friendUser.getEmail()));
            }
        }
        return friendsList;
    }
    /*
    public static void main(String[] args) {
        Controller c = new Controller();
        System.out.println(c.getFriendsByUserId(2));
    }
     */
}
